//
//  main.cpp
//  lesson02
//
//  Created by ryu on 2021/8/15.
//





#include <iostream>
using namespace std;

void mySwap01(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

//void mySwap02(string a, string b) {
//    string temp = a;
//    a = b;
//    b = temp;
//}

//2. 地址传递
void mySwap02(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void mySwap03(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

//返回局部变量引用
int& test01() {
    int a = 10; //局部变量
    return a;
}

//返回静态变量引用
int& test02() {
    static int a = 20;
    return a;
}

//发现是引用，转换为 int* const ref = &a;
void func(int& ref){
    ref = 100; // ref是引用，转换为*ref = 100
}

int func(int a, int b = 10, int c = 10) {
    return a + b + c;
}

//1. 如果某个位置参数有默认值，那么从这个位置往后，从左向右，必须都要有默认值
//2. 如果函数声明有默认值，函数实现的时候就不能有默认参数
int func2(int a = 10, int b = 10);
int func2(int a, int b) {
    return a+b;
}

class Circle{
    const double pi = 3.14;
public:
    int radius;
    int func(){
        return pi * radius * radius;
    }
};

class Cube{
public:
    //同java如果是放在public之外，相当于使用private修饰构造
    Cube(){
        r = 10;
    }
    ~Cube(){
        cout<<"Cube的析构函数"<<endl;
    }
    
    static void func(){
        cout<<"Cube的静态函数"<<endl;
    }
    //拷贝构造
    Cube(const Cube *c){
        cout<<"Cube的拷贝构造函数"<<endl;
        r = c->r;
    }
    
    Cube(const Cube &c){
        cout<<"Cube的拷贝构造函数"<<endl;
        r = c.r;
    }
    void setR(int edge){
        r = edge;
    }
    int volume(){
        return r*r*r;
    }
    int area(){
        return 6*r*r;
    }
    
private:
    int r;
};

//包含纯虚函数的类为抽象类，不能被实例化
class Animal{
public:
    //改写成纯虚函数
//    virtual void speak(){
//        cout<<"动物能说话"<<endl;
//    }
    virtual void speak() = 0;
};

class Cat :public Animal{
    void speak() override{
        cout<<"小猫喵喵喵"<<endl;
    }
    
};
class Dog :public Animal{
public:
    void speak() override{
        cout<<"小狗汪汪汪"<<endl;
    }
    ~Dog(){
        cout<<"destructor Dog"<<endl;
    }
};

void doSpeak(Animal &animal){
    animal.speak();
}
int main(int argc, const char * argv[]) {
    
    
//    int a = 10;
//    int &b = a;
//
//   /*
//    指针：指针是一个变量，只不过这个变量存储的是一个地址，指向内存的一个存储单元；
//    而引用跟原来的变量实质上是同一个东西，只不过是原变量的一个别名而已
//    */
//
//    cout << "a = " << a << endl;
//    cout << "b = " << b << endl;
//
//    b = 100;
//
//    cout << "a = " << a << endl;
//    cout << "b = " << b << endl;
    
    //引用就是某个目标变量的“别名”（alias）
    
//    int a = 10;
//    int b = 20;
//    int &c; //错误，引用必须初始化
//    int &c = a; //一旦初始化后，就不可以更改，可以用java思想理解。A a = new A() a是变量名，new A()则是引用。引用自始至终在内存都不会变
////    c = b; //这是赋值操作，不是更改引用
//
//    cout << "a = " << a << endl;
//    cout << "b = " << b << endl;
//    cout << "c = " << c << endl;
//
//    cout << "c = " << &c << endl;
//    c = b;
//    cout << "c = " << c << endl;
//    string c = "c";
//    string d = "d";
    
    
    
//    mySwap02(&a, &b);
    
//    mySwap01(a, b);
////    mySwap03(a, b);
//    cout<<a<<endl;
    
    //不能返回局部变量的引用
//        int& ref = test01();
//        cout << "ref = " << ref << endl;
//        cout << "ref = " << ref << endl;
//
//
//    const int *p1 = &a;
//
//
//    int * const p2 = &a;
//    int a = 10;
//
//        //自动转换为 int* const ref = &a; 指针常量是指针指向不可改，也说明为什么引用不可更改
//        int& ref = a;
//        ref = 20; //内部发现ref是引用，自动帮我们转换为: *ref = 20;
//
//        cout << "a:" << a << endl;
//        cout << "ref:" << ref << endl;
//
//        func(a);
//    cout << "ref:" << ref << endl;
//
//    cout << "ret = " << func(20, 20) << endl;
//        cout << "ret = " << func(100) << endl;
    
//    Circle circle;
//    circle.radius = 10;
//
//    cout<<circle.func()<<endl;
    
    Cube cube;
    cube.setR(13);
    cout<<cube.area()<<endl;
    cout<<cube.volume()<<endl;
    
    //如果引用参数，可以将变量直接传递
    
//    Cube cube2(&cube);//指针*和引用&(内存地址)
//    Cube *c = &cube;
//    cout<<((Cube *)&cube)->area()<<endl;
//    Cube cube3 = cube; //会调用拷贝构造函数
//
//    Cube::func();
    
    
    //拷贝构造函数必须在创建对象时使用
    
    Cat cat;
    doSpeak(cat);
    
    Cube* c2 = new Cube;

    Dog dog;
    doSpeak(dog);
    
    delete c2;
    cout<<"main返回"<<endl;
    
    //组装电脑场景。继承、多态、纯虚析构函数、实例化、面向对象基本设计
    
    
    
    
    return 0;
}
